<!DOCTYPE html>
<html>
  <head>
    <title>Where</title>
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
		<meta charset="utf-8">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.css"/>
    <script src="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.js"></script>
  </head>
  <body>
    <div id="map"></div>
    <a id="share" class="hide"><div class="stick button">Share</div></a>
    <div id="link" class="hide">
      <p>Copy and Paste this URL to your friends to share your location:</p>
      <center>
        <p id="follow">Location sharing not available!</p>
      </center>
      <p><b>Note</b>: Location may not sync when your device's screen is off or the tab is out of focus. You'd need to install this as an app for that to work.</p>
      <center>
        <a id="close"><div class="button">Close</div></a>
      </center>
    </div>
    <textarea style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 5em;" id="debug"></textarea>
    <style>
      html, body, #map {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
        font-family: Arial;
        font-size: 16pt;
        z-index: 1;
      }
      .stick {
        position: absolute;
        bottom: 1em;
        right: 1em;
      }
      .button {
        display: inline-block;
        padding: 1em;
        opacity: .5;
        background: blue;
        color: white;
        z-index: 7;
        transition: .25s all;
      }
      .button:hover {
        opacity: 1;
      }
      .hide {
        display: none;
      }
      #link {
        position: absolute;
        padding: 1em;
        top: 2em;
        left: 2em;
        right: 2em;
        bottom: 2em;
        background: white;
        overflow: scroll;
        z-index: 9;
      }
      #follow {
        background: #EEE;
        padding: .5em;
        word-wrap: break-word;
      }
    </style>
    <script src="/jquery.js"></script>
    <script src="/gun.js"></script>
    <script>
      function Where(opt, cb){
        // a small wrapper around Leaflet for map tracking.
        var where = {};
        where.opt = opt || {};
        where.opt.zoom = where.opt.zoom || {};
        where.opt.err = where.opt.err || function(){};

        where.map = L.map('map', { zoom: where.opt.zoom.level });

        where.opt.tile = where.opt.tile || L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
          maxZoom: where.opt.zoom.max,
          minZoom: where.opt.zoom.min,
          detectRetina: true,
          attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        });
        where.map.addLayer(where.opt.tile);

        where.opt.zoom.ing = where.opt.zoom.ing || function(){
          where.opt.zoom.level = where.map.getZoom();
        }
        where.map.on('zoomstart', where.opt.zoom.ing, where.opt.err);
        where.map.on('zoomend', where.opt.zoom.ing, where.opt.err);
        where.map.on('zoomlevelschange', where.opt.zoom.ing, where.opt.err);

        where.update = function(latlng){
          if((+new Date) - where.update.last < 400){
            clearTimeout(where.update.to);
            where.update.to = setTimeout(function(){
              where.update(latlng);
            });
            return;
          }
          where.map.setView(latlng, where.opt.zoom.level, {animate: true});
          where.marker = where.marker || L.marker().setLatLng(latlng).addTo(where.map);
          where.marker.setLatLng(latlng).update();
          where.update.last = (+new Date);
        }

        if(where.opt.track){
          where.map.on('locationfound', function(pos){
            where.update(pos.latlng);
            where.opt.track(pos);
          });

          where.map.locate({
            setView: true,
            zoom: where.opt.zoom.level,
            watch: where.opt.continuous || true,
            timeout: where.opt.timeout || 10000,
            maximumAge: where.opt.maximumAge || 0,
            enableHighAccuracy: where.opt.enableHighAccuracy || false
          });
        }

        return where;
      }
    </script>
    <script>
      ;(function(){
        // the actual GPS tracking app!
        var gun = Gun(location.origin + '/gun');
        var gps = {};
        gps.opt = {
          continuous: true, // get location just once uses `getCurrentPosition()` while continuously uses `watchPosition()`
          enableHighAccuracy: true, // HighAccuracy uses more resources, https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions
          timeout: 5000, // have this long to get data before erring.
          maximumAge: 0, // set to 0 to actually track.
          zoom: {max: 18, level: 13, min: 12}
        }
        function start(){
          gps.follow = (window.location.hash || '').slice(1);
          if(gps.follow){
            gps.where = gps.where || Where(gps.opt);
            gps.ref = gun.get('gps/' + gps.follow);
            gps.ref.on(function(latlng){
              //$('#debug').value = 'track ' + JSON.stringify(latlng);
              gps.where.update(latlng);
            });
            $('#share').addClass("hide");
          } else {
            document.cookie = 'gps=' + (gps.track = (document.cookie.match(/gps\=(.*?)(\&|$|\;)/i)||[])[1] || Gun.text.random(5)); // trick with cookies!
            gps.ref = gun.get('gps/' + gps.track);
            gps.opt.track = function(pos){
              pos = pos.latlng;
              if(gps.follow
              || Gun.time.is() - gps.when < 1000
              || gps.last && gps.last.lat == pos.lat && gps.last.lng == pos.lng){
                return; // throttle!
              }
              gps.when = Gun.time.is();
              gps.ref.put(gps.last = pos);
              //$('#debug').value = JSON.stringify(gps.last);
            }
            gps.where = gps.where || Where(gps.opt);
            $('#follow').text(("where.gunDB.io/" || (location.origin + location.pathname)) + '#' + gps.track);
            $('#share').removeClass("hide");
            $('#share').on('click', function(){
              $('#link').toggleClass("hide");
            });
            $('#close').on('click', function(){
              $('#link').toggleClass("hide");
            });
          }
        }
        start();
        window.onhashchange = start;
      }());
    </script>
  </body>
</html>